package com.refusea.commons.media

import java.awt.Image
import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import java.io.File
import javax.imageio.ImageIO


internal const val JPEG = "JPEG"

/**
 * @author Zhang Yan, 2023/10/9
 **/
object Images {

    private const val BUFFER_SIZE: Int = 16 * 1024

    @JvmStatic
    fun getSize(file: File): Size {
        val image = ImageIO.read(file)
        return Size(image.width, image.height)
    }

    /**
     * scaled size: width prior
     *
     * 1) calculate height based on width,
     * 2) if height greater than original height, calculate width based on height
     *
     **/
    @JvmStatic
    fun scale(file: File, size: Size, format: String = JPEG, scale: Int = Image.SCALE_SMOOTH): ByteArray {

        val image = ImageIO.read(file)

        var width = size.width
        var height = width * image.height / image.width

        if (height > size.height) {
            height = size.height
            width = height * image.width / image.height
        }

        return scale(image, width, height, format, scale)
    }

    @JvmStatic
    fun getFormat(file: File): String? {
        val readers = ImageIO.getImageReaders(ImageIO.createImageInputStream(file))
        return if (readers.hasNext()) {
            readers.next().formatName
        } else {
            null
        }
    }

    @JvmStatic
    fun squareScale(
        file: File,
        width: Int,
        format: String = JPEG, scale: Int = Image.SCALE_SMOOTH,
    ): ByteArray {
        val image = ImageIO.read(file)

        val min = image.width.coerceAtMost(image.height)
        val x = if (image.width == min) 0 else (image.width - min) / 2
        val y = if (image.height == min) 0 else (image.height - min) / 2

        val square = image.getSubimage(x, y, min, min)

        return scale(square, width, width, format, scale)
    }

    private fun scale(
        image: BufferedImage,
        width: Int,
        height: Int,
        format: String = JPEG, scale: Int = Image.SCALE_SMOOTH,
    ): ByteArray {
        val buff = BufferedImage(width, height, image.type)
        val graph = buff.createGraphics()
        try {
            graph.drawImage(image.getScaledInstance(width, height, scale), 0, 0, null)
        } finally {
            graph.dispose()
        }
        val output = ByteArrayOutputStream(BUFFER_SIZE)
        ImageIO.write(buff, format, output)
        return output.toByteArray()
    }
}

